import React from "react";
import ReactDataSheet from "react-datasheet";
import { Button } from "antd";
import "react-datasheet/lib/react-datasheet.css";
import "./index.less";



/**
 * 一个基于react-datasheet可编辑，拖拽shift复制，alt递增的表格组件
 *
 * @param    {function}  onSelect      按下shift拖动选中单元格的回调
 * @param    {function}  onChange      表格内容更改后的回调
 * @param    {function}  onCellsChange 单元格数据更改后的回调
 * @param    {data}   data             表格数据的二维数组（必须）
 * @param    {bol}  fixHeader          固定表头 false
 * @param    {bol}  fixCol             固定列头
 * @param    {bol}  isScroll           滚动
 * @returns  可编辑，拖拽复制，递增的表格组件
 * @date     2018-08-24
 */


let firstValue = null;
// let secValue = null;
let flag = true;
let canScroll = true;
const shiftArr = [];
const selectArr = [];
const mouseArr = [];

export default class ExcelTable extends React.Component {

  constructor(props) {
    super(props);
    // this.state = {
    let grid = [
      [{ value: "技能组" }, { value: "预测日期" }, { value: "模型预测值" }, { value: "事件量" }, { value: "模型修改量" }, { value: "综合预测值" },],
      [{ value: "安全线" }, { value: "2020-07-01" }, { value: "532" }, { value: "0" }, { value: "0" }, { value: "555" },],
      [{ value: "安全线" }, { value: "2020-07-02" }, { value: "533" }, { value: "0" }, { value: "0" }, { value: "555" },],
      [{ value: "安全线" }, { value: "2020-07-03" }, { value: "534" }, { value: "0" }, { value: "0" }, { value: "555" },],
      [{ value: "安全线" }, { value: "2020-07-04" }, { value: "535" }, { value: "0" }, { value: "0" }, { value: "555" },],
      [{ value: "安全线" }, { value: "2020-07-05" }, { value: "536" }, { value: "0" }, { value: "0" }, { value: "555" },],
      [{ value: "安全线" }, { value: "2020-07-06" }, { value: "537" }, { value: "0" }, { value: "0" }, { value: "555" },],
      [{ value: "安全线" }, { value: "2020-07-07" }, { value: "538" }, { value: "0" }, { value: "0" }, { value: "555" },],
      [{ value: "安全线" }, { value: "2020-07-08" }, { value: "539" }, { value: "0" }, { value: "0" }, { value: "555" },],
      [{ value: "安全线" }, { value: "2020-07-09" }, { value: "520" }, { value: "0" }, { value: "0" }, { value: "555" },],
      [{ value: "安全线" }, { value: "2020-07-10" }, { value: "521" }, { value: "0" }, { value: "0" }, { value: "555" },],
      [{ value: "安全线" }, { value: "2020-07-11" }, { value: "522" }, { value: "0" }, { value: "0" }, { value: "555" },],
      [{ value: "安全线" }, { value: "2020-07-12" }, { value: "523" }, { value: "0" }, { value: "0" }, { value: "555" },],
    ]

    // }
    this.state = {
      event: { start: {}, end: {} },
      grid: grid || [],
      header: grid && grid[0],
    };
  }

  componentDidMount() {
    window.onkeydown = this.onKeyDown;
    window.onkeyup = this.onkeyUp;
    window.onmousedown = this.onWindowMousedown;
    window.onmouseup = this.onWindowMouseUp;
    // window.onmousemove = this.onWindowMouseMove;
    // this.move = true;
  }

  // componentWillReceiveProps(nextProps) {
  //   const { data } = nextProps;
  //   if (data) {
  //     this.setState({
  //       grid: data,
  //       header: data[0],
  //     });
  //   }
  // }

  onmousedown = (e) => {
    this.addEvent();
    this.isCopy = true;
  }

  onWindowMouseUp = () => {
    this.isCopy = false;
    mouseArr.length = 0;
  }

  onWindowMousedown = (e) => {
    const str = e.target.className;
    if (str.includes('value-viewer') || str.includes('cell')) {
      this.allSelect = true;
    } else {
      this.allSelect = false;
    }
  }

  onMouseLeave = () => {
    this.leave = true;
    this.addScrollTop();
  }

  onMouseEnter = () => {
    this.leave = false;
  }

  onKeyDown = (e) => {
    const { keyCode, key } = e;
    if (this.allSelect && (e.metaKey && keyCode === 65 || e.ctrlKey && keyCode === 65)) {
      e.returnValue = false; // 禁止ctrl+a全选
      const { grid } = this.state;
      const event = { start: { i: 0, j: 0 }, end: { i: grid && grid.length - 1, j: grid && grid[0] && grid[0].length - 1 } };
      this.setState({ event });
    }
    // if (keyCode === 16) {
    //   shiftArr.push(keyCode);
    // }
    // if (shiftArr.length === 2) {
    //   const { grid } = this.state;
    //   const event = { start: { i: 0, j: 0 }, end: { i: grid && grid.length - 1, j: grid && grid[0] && grid[0].length - 1 } };
    //   this.setState({ event });
    // }

    if (flag) {
      if (keyCode === 16 || key === 'Shift' || keyCode === 18 || key === 'Alt') {
        firstValue = null;
        this.setState({ isShift: true, isAlt: keyCode === 18 });
      }
      flag = false;
    }
  }

  onkeyUp = (e) => {
    selectArr.length = 0;
    flag = true;
    const { keyCode, key } = e;
    if (keyCode === 91) {
      this.ctrl = false;
    }
    if (keyCode === 16 || key === 'Shift' || keyCode === 18 || key === 'Alt') {
      this.setState({ isShift: !keyCode === 16, isAlt: !keyCode === 18 });
    }
    setTimeout(() => {
      shiftArr.length = 0;
    }, 500);
  }

  onSelect = (e) => {
    const { start, end } = e;
    const { i: si, j: sj } = start;
    const { i: ei, j: ej } = end;
    if (this.selectEndi === ei && this.selectEndj === ej) {
      return;
    }
    const {
      grid, isAlt, isShift, event,
    } = this.state;
    const num = (nums) => parseFloat(nums).toString() !== 'NaN';
    this.selectEndi = ei;
    this.selectEndj = ej;
    event.end = e.end;
    event.start = e.start;
    this.setState({ event });
    if (isAlt) {
      selectArr.length === 0 && selectArr.push(parseInt(grid[si][sj].value));
      selectArr.length === 1 && selectArr.push(parseInt(grid[ei][ej].value));
      if (!num(selectArr[0]) || !num(selectArr[1])) {
        return;
      }
      if (!num(firstValue)) {
        firstValue = parseInt(grid[si][sj].value);
      }
      const differ = selectArr[1] - selectArr[0];
      firstValue = NP.round(NP.plus(firstValue, differ), 2);
      grid[ei][ej].value = firstValue;
      grid[ei][ej].className = 'blue';
      this.setState({ grid });
    } else if (isShift) {
      selectArr.length === 0 && selectArr.push(parseInt(grid[si][sj].value));
      if (!num(selectArr[0])) {
        return;
      }
      if (!num(firstValue)) {
        firstValue = parseInt(grid[si][sj].value);
      }
      grid[ei][ej].value = firstValue;
      grid[ei][ej].className = 'blue';
      this.setState({ grid });
    }
    // let value1 = parseFloat(grid[si][sj].value);
    // const value2 = grid[si][sj].value;
    // if (!num(firstValue)) {
    //   firstValue = value1;
    // }
    // if (!num(grid[si][sj].value) || !num(grid[ei][ej].value)) { // 如果不是数字
    //   value1 = value2;
    // }
    // if (num(firstValue) && num(parseFloat(grid[ei][ej].value) - firstValue)) {
    //   if (!num(secValue)) {
    //     secValue = parseFloat(grid[ei][ej].value) - firstValue;
    //   }
    // }
    // if (this.state.isShift) {
    //   if (!num(grid[si][sj].value) || !num(grid[ei][ej].value)) { // 如果不为数字
    //     firstValue = value1;
    //   } else {
    //     firstValue = NP.round(NP.plus(firstValue, secValue), 2);
    //   }
    //   if (!grid[ei][ej].readOnly) {
    //     grid[ei][ej].value = this.state.isAlt ? firstValue : value1;
    //     grid[ei][ej].className = 'blue';
    //   }
    //   this.setState({ grid });
    //   grid[ei][ej] && this.props.onSelect && this.props.onSelect(event, grid[ei][ej]);
    // }
    grid[ei][ej] && this.props.onSelect && this.props.onSelect(event, grid[ei][ej]);
  }

  getFixHeader = (fixHeader, dispearHeader) => { // 复制表格首行固定表头
    if (!fixHeader) {
      return null;
    }
    const isScroll = this.props.height ? this.state.grid.length * 30 >= this.props.height : false;
    return (
      <div
        className="excelTable"
        type="header"
        ref={(e) => { this.header = e; }}
        style={{ left: -this.state.scrollLeft, overflowY: isScroll ? 'scroll' : '', visibility: dispearHeader ? 'hidden' : undefined }}>
        <span className="data-grid-container">
          <table className="data-grid" >
            <tbody>
              <tr>
                {
                  this.state.header && this.state.header.map((i, index) => {
                    return (<td key={`header-${index}`} className="cell read-only"><span className="value-viewer">{i.value}</span></td>);
                  })
                }
              </tr>
            </tbody>
          </table>
        </span>
      </div>
    );
  }

  addScrollTop = () => {
    if (this.isCopy && this.leave) {
      const scrollInerval = setInterval(() => {
        if (!this.isCopy || !this.leave) {
          clearInterval(scrollInerval);
        }
        this.bodyBox.scrollTop = this.bodyBox.scrollTop + 10;
        // this.bodyBox.scrollLeft = this.bodyBox.scrollLeft + 10;
        // if (mouseArr.length > 1) {
        //   const x = (mouseArr[1].y - mouseArr[0].y) - (mouseArr[1].x - mouseArr[0].x);
        //   x > 0 ? this.bodyBox.scrollTop = this.bodyBox.scrollTop + 10 : this.bodyBox.scrollLeft = this.bodyBox.scrollLeft + 10;
        // }
      }, 50);
    }
  }

  handleScroll = () => {
    if (!canScroll) {
      return;
    }
    const { header, bodyBox } = this;
    const { scrollLeft, scrollTop } = bodyBox;
    const headerHeight = header.offsetHeight;
    this.setState({ scrollLeft, scrollTop, headerHeight });
    canScroll = false;
    setTimeout(() => {
      canScroll = true;
    }, 300);
  }


  addEvent = () => {
    window.onkeydown = this.onKeyDown;
    window.onkeyup = this.onkeyUp;
    window.onmouseup = this.onWindowMouseUp;
  }

  // const onCellsChanged = (changes) => changes.forEach(({cell, row, col, value}) => console.log("New expression :" + value))

  fullScreen = () => {
    const de = document.getElementById('excelTable');
    de.style.background = "#fff";
    de.style.display = "flex";
    de.style.justifyContent = "center";
    de.style.alignItems = "center";
    if (de.requestFullscreen) {
      de.requestFullscreen();
    } else if (de.mozRequestFullScreen) {
      de.mozRequestFullScreen();
    } else if (de.webkitRequestFullScreen) {
      de.webkitRequestFullScreen();
    }
  }

  render() {

    const {
      fixHeader = false, fixCol = false, height = '', noScolly = false,
    } = this.props;
    const dispearHeader = noScolly && this.state.scrollLeft;
    const first = this.state.header && this.state.header[0].value;

    return (
      <div onClick={this.addEvent}>
        <Button onClick={this.fullScreen}>全屏</Button>
        <div className="excelBox">
          {/* <div
          className="excelTable"
        >
        <ReactDataSheet
          style={{ width: "100%", height: "100%", }}
          data={this.state.grid}
          valueRenderer={cell => {
            console.log(cell, "cell")
            return cell.value == 537 ? <span style={{color: "red", background: "orange"}}>{cell.value}</span> : cell.value
          }}
          onCellsChanged={changes => {
            const grid = this.state.grid.map(row => [...row]);
            changes.forEach(({ cell, row, col, value }) => {
              grid[row][col] = { ...grid[row][col], value };
            });
            this.setState({ grid });
          }}
        />
        </div> */}
          <div
            id='excelTable'
            onMouseDown={this.onmousedown}
            onMouseEnter={this.onMouseEnter}
            onMouseLeave={this.onMouseLeave}
            style={{ maxHeight: height }}
            className="excelTable"
            onScroll={this.handleScroll}
            ref={(e) => { this.bodyBox = e; }}>
            {this.state.grid ?
              <span className="bbottom">
                <ReactDataSheet
                  selected={this.state.event}
                  onSelect={this.onSelect}
                  data={this.state.grid}
                  valueRenderer={(cell) => cell.value}
                  onContextMenu={(e, cell) => (cell.readOnly ? e.preventDefault() : null)}
                  onCellsChanged={(changes) => {
                    const grid = this.state.grid.map((row) => [...row]);
                    changes.forEach(({
                      row, col, value,
                    }) => {
                      grid[row][col] = { ...grid[row][col], value };
                      grid[row][col].className = 'blue';
                    });
                    this.props.onCellsChange && this.props.onCellsChange(changes);
                    this.setState({ grid }, () => {
                      this.props.onChange && this.props.onChange(grid);
                    });
                  }} />
              </span>
              :
              <p style={{ textAlign: 'center', margin: '20px' }}>暂无数据</p>
            }
          </div>
          {this.getFixHeader(this.props.fixHeader, dispearHeader)}
          <div style={{ maxHeight: '500px', overflow: 'hiddden' }}>
            <div className="excelTable" type="colums" style={{ top: -this.state.scrollTop }}>
              <span className="data-grid-container">
                <table className="data-grid" >
                  <tbody>
                    {fixCol &&
                      this.state.grid && this.state.grid.map((i, index) => {
                        return (
                          <tr key={`col-${index}`} ><td className="cell read-only"><span className="value-viewer">{i[0].value}</span></td></tr>
                        );
                      })
                    }
                  </tbody>
                </table>
              </span>
            </div>
          </div>
          <div className="excelTable" type="header-first">
            <span className="data-grid-container">
              <table className="data-grid" >
                <tbody>
                  {fixHeader && fixCol && this.state.headerHeight && <tr key="first-header"><td style={{ height: this.state.headerHeight - 1 }} className="cell read-only"><span className="value-viewer">{first}</span></td></tr>}
                </tbody>
              </table>
            </span>
          </div>

        </div>
      </div>
    )
  }

}
